home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / mosmllib / Nonstdio.sml < prev    next >
Encoding:
Text File  |  1997-08-18  |  9.3 KB  |  308 lines  |  [TEXT/R*ch]

  1. (* Nonstdio.sml *)
  2.  
  3. (*
  4.   This unit extends BasicIO. Since Moscow ML doesn't provide
  5.   legal means for creating "derived" units, we have to use some
  6.   "magic", to get into abstract Basicio.instream and
  7.   Basicio.outstream values.
  8.  
  9.   The same problem arises with CharArray.array values.
  10. *)
  11.  
  12. open BasicIO;
  13.  
  14. (* Caml Light "channels" *)
  15.  
  16. (* We define in_channel and out_channel as in Basicio *)
  17. (* for internal use only. *)
  18.  
  19. prim_type in_channel and out_channel;
  20.  
  21. prim_val open_descriptor_in : int -> in_channel = 1 "open_descriptor";
  22.         (* [open_descriptor_in fd] returns a buffered input channel
  23.            reading from the file descriptor [fd]. The file descriptor [fd]
  24.            must have been previously opened for reading, else the behavior is
  25.        undefined. *)
  26.  
  27. prim_val open_descriptor_out : int -> out_channel = 1 "open_descriptor";
  28.         (* [open_descriptor_out fd] returns a buffered output channel
  29.            writing to the file descriptor [fd]. The file descriptor [fd]
  30.            must have been previously opened for writing, else the behavior is
  31.        undefined. *)
  32.  
  33. prim_val input_char_ : in_channel -> char = 1 "input_char";
  34.         (* Read one character from the given input channel.
  35.            Raise [Size] if there are no more characters to read. *)
  36.  
  37. prim_val input_binary_int_ : in_channel -> int = 1 "input_int";
  38.         (* Read an integer encoded in binary format from the given input
  39.            channel. See [output_binary_int].
  40.            Raise [Size] if an end of file was reached while reading the
  41.        integer. *)
  42.  
  43. prim_val input_value_ : in_channel -> 'a = 1 "intern_val";
  44.         (* Read the representation of a structured value, as produced
  45.            by [output_value], and return the corresponding value. *)
  46.  
  47. prim_val seek_in_ : in_channel -> int -> unit = 2 "seek_in"
  48.         (* [seek_in chan pos] sets the current reading position to [pos]
  49.            for channel [chan]. *)
  50.  
  51. prim_val pos_in_ : in_channel -> int = 1 "pos_in";
  52.         (* Return the current reading position for the given channel. *)
  53.  
  54. prim_val in_channel_length_ : in_channel -> int = 1 "channel_size";
  55.         (* Return the total length (number of characters) of the
  56.            given channel. This works only for regular files. *)
  57.  
  58. prim_val fast_input :
  59.   in_channel -> string -> int -> int -> int = 4 "input";
  60.  
  61. prim_val fast_output :
  62.   out_channel -> string -> int -> int -> unit = 4 "output";
  63.  
  64. prim_val output_char_ : out_channel -> char -> unit = 2 "output_char"
  65.         (* Write one character on the given output channel. *)
  66.  
  67. prim_val output_byte_ : out_channel -> int -> unit = 2 "output_char"
  68.         (* Write one 8-bit integer (as the single character with that code)
  69.            on the given output channel. The given integer is taken modulo
  70.            256. *)
  71.  
  72. prim_val output_binary_int_ : out_channel -> int -> unit = 2 "output_int";
  73.         (* Write one integer in binary format on the given output channel. *)
  74.  
  75. prim_val output_value_ : out_channel -> 'a -> unit = 2 "extern_val";
  76.         (* Write the representation of a structured value of any type
  77.            to a channel. *)
  78.  
  79. prim_val seek_out_ : out_channel -> int -> unit = 2 "seek_out"
  80.         (* [seek_out chan pos] sets the current writing position to [pos]
  81.            for channel [chan]. This works only for regular files. On
  82.            files of other kinds (such as terminals, pipes and sockets,)
  83.        the behavior is unspecified. *)
  84.  
  85. prim_val pos_out_ : out_channel -> int = 1 "pos_out";
  86.         (* Return the current writing position for the given channel. *)
  87.  
  88. type file_perm = int;
  89.  
  90. datatype open_flag =
  91.     O_RDONLY                       (* `open' read-only *)
  92.   | O_WRONLY                       (* `open' write-only *)
  93.   | O_RDWR                         (* `open' for reading and writing *)
  94.   | O_APPEND                       (* `open' for appending *)
  95.   | O_CREAT                        (* create the file if nonexistent *)
  96.   | O_TRUNC                        (* truncate the file to 0 if it exists *)
  97.   | O_EXCL                         (* fails if the file exists *)
  98.   | O_BINARY                       (* `open' in binary mode *)
  99.   | O_TEXT                         (* `open' in text mode *)
  100. ;
  101.  
  102. prim_val sys_open :
  103.   string -> open_flag list -> file_perm -> int = 3 "sys_open"
  104.         (* Open a file. The second argument is the opening mode.
  105.            The third argument is the permissions to use if the file
  106.            must be created. The result is a file descriptor opened on the
  107.            file. *)
  108. prim_val sys_close :
  109.   int -> unit = 1 "sys_close"
  110.         (* Close a file descriptor. *)
  111.  
  112.  
  113. (* Moscow ML streams *)
  114.  
  115. type buffer = string;
  116.  
  117. (* Since instream and outstream are declared in Basicio *)
  118. (* as abstract types, we need a dirty trick to get access *)
  119. (* to their representation.  :-< *)
  120.  
  121. type instream_  = { closed: bool, ic: in_channel } ref;
  122. type outstream_ = { closed: bool, oc: out_channel } ref;
  123.  
  124. prim_val fromI : instream -> instream_   = 1 "identity";
  125. prim_val fromO : outstream -> outstream_ = 1 "identity";
  126. prim_val mkI   : instream_ -> instream   = 1 "identity";
  127. prim_val mkO   : outstream_ -> outstream = 1 "identity";
  128.  
  129. (* The same trick to access the internals of CharArray.array. *)
  130.  
  131. prim_val fromCA : CharArray.array -> string ref = 1 "identity";
  132.  
  133. fun open_in_gen_ mode rights filename =
  134.   open_descriptor_in (sys_open filename mode rights)
  135. ;
  136.  
  137. val open_in_bin_ = open_in_gen_ [O_RDONLY, O_BINARY] 0;
  138.  
  139. fun open_out_gen mode rights filename =
  140.   open_descriptor_out(sys_open filename mode rights)
  141. ;
  142.  
  143. prim_val s_irall : file_perm = 0 "s_irall";
  144. prim_val s_iwall : file_perm = 0 "s_iwall";
  145. prim_val s_ixall : file_perm = 0 "s_ixall";
  146.  
  147. val open_out_bin_ =
  148.   open_out_gen [O_WRONLY, O_TRUNC, O_CREAT, O_BINARY]
  149.                (s_irall + s_iwall);
  150.  
  151. val open_out_exe_ =
  152.   open_out_gen [O_WRONLY, O_TRUNC, O_CREAT, O_BINARY]
  153.                (s_irall + s_iwall + s_ixall);
  154.  
  155. fun raiseIo fcn nam exn = 
  156.     raise SysErr ("Nonstdio." ^ fcn ^ " on " ^ nam, NONE);
  157.  
  158. fun raiseClosed fcn nam = 
  159.     raiseIo fcn nam (Fail "Stream is closed");
  160.  
  161. fun open_in_bin s =
  162.   mkI (ref {closed=false, ic=open_in_bin_ s})
  163.   handle exn as SysErr _ => raiseIo "open_in_bin" s exn;
  164.  
  165. fun fast_really_input is (buff : string) offs len =
  166.   let val ref {closed, ic} = fromI is in
  167.     if closed then
  168.       raiseClosed "fast_really_input" ""
  169.     else if len <= 0 then () else
  170.       case fast_input ic buff offs len of
  171.         0 => raise Fail "fast_really_input: unexpected end of file"
  172.       | r => fast_really_input is buff (offs+r) (len-r)
  173.   end;
  174.  
  175. fun buff_input is (buff : CharArray.array) offs len =
  176.   let val ref {closed, ic} = fromI is in
  177.     if closed then
  178.       0
  179.     else
  180.       let val ref sbuff = fromCA buff in
  181.         if len < 0 orelse offs < 0 orelse offs+len > size sbuff then
  182.           raise Fail "buff_input"
  183.         else
  184.           fast_input ic sbuff offs len
  185.       end
  186.   end;
  187.  
  188. fun input_char is =
  189.   let val ref {closed, ic} = fromI is in
  190.     if closed then
  191.       raiseClosed "input_char" ""
  192.     else
  193.       input_char_ ic
  194.   end;
  195.  
  196. fun input_binary_int is =
  197.   let val ref {closed, ic} = fromI is in
  198.     if closed then
  199.       raiseClosed "input_binary_int" ""
  200.     else
  201.       input_binary_int_ ic
  202.   end;
  203.  
  204. fun input_value is =
  205.   let val ref {closed, ic} = fromI is in
  206.     if closed then
  207.       raiseClosed "input_value" ""
  208.     else
  209.       input_value_ ic
  210.   end;
  211.  
  212. fun seek_in is =
  213.   let val ref {closed, ic} = fromI is in
  214.     if closed then
  215.       raiseClosed "seek_in" ""
  216.     else
  217.       seek_in_ ic
  218.   end;
  219.  
  220. fun pos_in is =
  221.   let val ref {closed, ic} = fromI is in
  222.     if closed then
  223.       raiseClosed "pos_in" ""
  224.     else
  225.       pos_in_ ic
  226.   end;
  227.  
  228. fun in_stream_length is =
  229.   let val ref {closed, ic} = fromI is in
  230.     if closed then
  231.       raiseClosed "in_stream_length" ""
  232.     else
  233.       in_channel_length_ ic
  234.   end;
  235.  
  236. fun open_out_bin s =
  237.   mkO(ref {closed=false, oc=open_out_bin_ s})
  238.   handle exn as SysErr _ => raiseIo "open_out_bin" s exn;
  239.  
  240. fun open_out_exe s =
  241.   mkO(ref {closed=false, oc=open_out_exe_ s})
  242.   handle exn as SysErr _ => raiseIo "open_out_exe" s exn;
  243.  
  244. fun buff_output os (buff : CharArray.array) offs len =
  245.   let val ref {closed, oc} = fromO os in
  246.     if closed then
  247.       raiseClosed "buff_output" ""
  248.     else
  249.       let val ref sbuff = fromCA buff in
  250.         if len < 0 orelse offs < 0 orelse offs+len > size sbuff then
  251.           raise Fail "buff_output"
  252.         else
  253.           fast_output oc sbuff offs len
  254.       end
  255.   end;
  256.  
  257. fun output_char os (c : char) =
  258.   let val ref {closed, oc} = fromO os in
  259.     if closed then
  260.       raiseClosed "output_char" ""
  261.     else
  262.       output_char_ oc c
  263.   end;
  264.  
  265. fun output_byte os (c : int) =
  266.   let val ref {closed, oc} = fromO os in
  267.     if closed then
  268.       raiseClosed "output_byte" ""
  269.     else
  270.       output_byte_ oc c
  271.   end;
  272.  
  273. fun output_binary_int os i =
  274.   let val ref {closed, oc} = fromO os in
  275.     if closed then
  276.       raiseClosed "output_binary_int" ""
  277.     else
  278.       output_binary_int_ oc i
  279.   end;
  280.  
  281. fun output_value os v =
  282.   let val ref {closed, oc} = fromO os in
  283.     if closed then
  284.       raiseClosed "output_value" ""
  285.     else
  286.       output_value_ oc v
  287.   end;
  288.  
  289. fun seek_out os pos =
  290.   let val ref {closed, oc} = fromO os in
  291.     if closed then
  292.       raiseClosed "seek_out" ""
  293.     else
  294.       seek_out_ oc pos
  295.   end;
  296.  
  297. fun pos_out os =
  298.   let val ref {closed, oc} = fromO os in
  299.     if closed then
  300.       raiseClosed "pos_out" ""
  301.     else
  302.       pos_out_ oc
  303.   end;
  304.  
  305. fun file_exists filename =
  306.   (sys_close(sys_open filename [O_RDONLY] 0); true)
  307.      handle SysErr _ => false;
  308.